package Concurrency2.Inteview01_ThreadPool.version03;

import Concurrency2.Inteview01_ThreadPool.version01.ThreadPool;
import Concurrency2.Inteview01_ThreadPool.version01.WorkerThread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 作用:
 * version01线程池-基本的线程池功能
 * version02线程池-增加对线程数量(初始化线程数, 核心线程数, 最大线程数), 以及队列任务数量限制
 * version03线程池-增加拒绝策略
 */
public class SimpleThreadPool implements ThreadPool {

    // 属性: 初始线程数
    private int initialSize;
    // 属性: 任务队列
    private BlockingQueue<Runnable> taskQueue;
    // 属性: 工作线程集合
    private List<WorkerThread> threads;
    // 属性: shutdown状态标志
    private volatile boolean isShutdown = false;

    // 属性: 核心线程数
    private int coreSize;
    // 属性: 最大线程数
    private int maxSize;
    // 属性: 队列数量
    private int queueSize;
    // 属性: 拒绝策略
    private RejectedExecutionHandler rejectedExecutionHandler;

    //构造: 创建具有多个参数的线程池
    public SimpleThreadPool(int initialSize, int maxSize, int coreSize, int queueSize, RejectedExecutionHandler rejectedExecutionHandler) {
        this.initialSize = initialSize;
        this.maxSize = maxSize;
        this.coreSize = coreSize;
        this.queueSize = queueSize;
        taskQueue = new LinkedBlockingQueue<>(queueSize); //初始化容量队列
        threads = new ArrayList<>(initialSize);
        this.rejectedExecutionHandler = rejectedExecutionHandler;
        // 初始化指定数量的工作线程, 并启动
        for (int i = 0; i < initialSize; i++) {
            WorkerThread workerThread = new WorkerThread(taskQueue);
            workerThread.start();
            threads.add(workerThread);
        }
    }

    /**
     * 功能1: 提交任务到线程池
     * 1, 提交任务到线程池
     * 2, 管理线程池中的数量(*)
     *
     * @param task 任务
     */
    @Override
    public void execute(Runnable task) {
        if (isShutdown) {
            throw new IllegalStateException("ThreadPool has been shutdown.");
        }
        //taskQueue.offer(task);
        // 状态1: 线程池内的存活线程数n小于核心线程数coreSize --> 创建线程, 马上执行task;
        // 状态2: n大于等于coreSize && 队列中task任务数<=queueSize --> 任务放入队列;
        // 状态3: 队列中task任务数>queueSize && n<=maxSize -->  创建线程, 执行task;
        // 状态4: 以上状态都不满足 --> 执行拒绝策略(该version直接抛出异常-任务执行失败)
        if (threads.size() < coreSize) {
            // 状态1
            addWorkerThread(task);
        } else if (!taskQueue.offer(task)/*状态2*/) {
            if (threads.size() < maxSize) {
                // 状态3
                addWorkerThread(task);
            } else {
                // 状态4 - 执行拒绝策略
                //throw new IllegalStateException("Task数超过任务队列容量, 任务执行失败!");
                this.rejectedExecutionHandler.rejectedExecution(task, this);
            }
        }
    }

    /**
     * 功能: 创建线程, 并执行任务
     */
    private void addWorkerThread(Runnable task) {
        WorkerThread workerThread = new WorkerThread(taskQueue);
        workerThread.start();
        threads.add(workerThread);
        try {
            taskQueue.put(task);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 功能2: 关闭线程池
     */
    @Override
    public void shutdown() {
        //1, 设置线程池状态
        isShutdown = true;
        //2, 中断worker线程
        for (WorkerThread worker : threads) {
            worker.interrupt();
        }
    }

    /**
     * 功能3: 立即关闭线程池
     *
     * @return 未执行的任务列表
     */
    @Override
    public List<Runnable> shutdownNow() {
        //1, 设置线程池状态
        isShutdown = true;
        //2, 保留为执行的任务作为结果返回
        List<Runnable> remainTask = new ArrayList<>();
        taskQueue.drainTo(remainTask);
        //3, 中断worker线程
        for (WorkerThread worker : threads) {
            worker.interrupt();
        }
        return remainTask;
    }
}
